/* Includes ------------------------------------------------------------------*/
#include "nril.h"
#include <string.h>

/* typedef -------------------------------------------------------------------*/ 
/* define --------------------------------------------------------------------*/
/* macro ---------------------------------------------------------------------*/
/* variables -----------------------------------------------------------------*/
struct RilDevice _rilDevice = {0};
/* function prototypes -------------------------------------------------------*/
/* functions -----------------------------------------------------------------*/
/*********************************************************************************************

  * @brief  Ril_Init
  * @param  *adapter, at adapter
  *         *config, config object  
  *         *driverName, find the device driver by name
  * @return 0, find the driver
  *         -6: no such device
  * @remark find the driver of device and init the ril obj 

  ********************************************************************************************/
int Ril_Init(struct NatAdapter *adapter, struct RilDeviceConfig *config, char *driverName)
{
    static const struct RilDeviceDriver RilDeviceDriverHead __attribute__((used, __section__("ril.device.0"))) = {0};
    static const struct RilDeviceDriver RilDeviceDriverTail __attribute__((used, __section__("ril.device.2"))) = {0};
	const struct RilDeviceDriver *driver;
	
    _rilDevice.adapter = adapter;
    _rilDevice.config = config;

    for(driver = &RilDeviceDriverHead + 1; driver < &RilDeviceDriverTail; driver++)
    {
        if(strcasecmp(driver->name, driverName) == 0)
        {
            _rilDevice.driver = (struct RilDeviceDriver *)driver;
            break;
        }
    }
    if(_rilDevice.driver == NULL)
    {   return -6;  }     // ENXIO
	
	return 0;
}
/*********************************************************************************************

  * @brief  RilDevice_ExecuteCommand
  * @param  *dev, ril device object pointer
  *         waitTime: wait time, unit is ms
  * 		*reponse, wait until match response
  *         *format, the command content format
  * @return 
  * @remark send command to ril at device 

  ********************************************************************************************/
int RilDevice_ExecuteCommand(struct RilDevice *dev, int32_t waitTime, char* response, char *format, ...)
{
	int result = -2;
	
	va_list args;
    va_start(args, format);
	result = _Nat_ExecuteCommand(dev->adapter, (struct Nat *)(dev->driver->at), waitTime, response, format, args);
	va_end(args);

	return result;
}
/*********************************************************************************************

  * @brief  RilDevice_SendRaw
  * @param  *dev, ril device object pointer
  *         waitTime: wait time, unit is ms
  * 		*reponse, wait until match response
  *         *packet: the packet of data which need send to device
  *			szie: the byte count of packet
  * @return 
  * @remark send command to ril at device 

  ********************************************************************************************/
int RilDevice_SendRaw(struct RilDevice *dev, int32_t waitTime, char *response, uint8_t *packet, size_t size)
{
	return Nat_SendRaw(dev->adapter, (struct Nat *)(dev->driver->at), waitTime, response, packet, size);
}
/*********************************************************************************************

  * @brief  RilDevice_ATTest
  * @param  
  * @return 
  * @remark send AT to ril at device to test if the device is activate

  ********************************************************************************************/
int RilDevice_ATTest(void)
{
	int result = -2;
	result = Nat_ExecuteCommand(_rilDevice.adapter, (struct Nat *)_rilDevice.driver->at, 1000, "OK", "AT");
	
	return result;
}
/*********************************************************************************************

  * @brief  RilDevice_ClearRxBuffer
  * @param  
  * @return 
  * @remark clear all old rx message

  ********************************************************************************************/
void RilDevice_ClearMessages(void)
{
	int result = -2;
	do
	{
		if(Nat_ExecuteCommand(_rilDevice.adapter, (struct Nat *)_rilDevice.driver->at, 0, 0, NULL) != 0)
		{	break;	}
	}while(1);
}

/*********************************************************************************************

  * ril device opertions

  ********************************************************************************************/
int RilDevice_Init(void)
{	return _rilDevice.driver->ops->init(&_rilDevice);	}
int RilDevice_StartUp(void)
{	return _rilDevice.driver->ops->startUp(&_rilDevice);	}
int RilDevice_ShutDown(void)
{	return _rilDevice.driver->ops->shutDown(&_rilDevice);	}
int RilDevice_Reset(bool useResetPin)
{	return _rilDevice.driver->ops->reset(&_rilDevice, useResetPin);	}
int RilDevice_Pdp(void)
{	return _rilDevice.driver->ops->pdp(&_rilDevice);	}

/*********************************************************************************************

  * ril devices sal api

  ********************************************************************************************/
int RilDevice_Release(struct RilDevice *device, struct Socket *socket)
{	return _rilDevice.driver->ops->opsSocket.release(device, socket);	}
int RilDevice_Connect(struct RilDevice *device, struct Socket *socket, const struct sockaddr *name, socklen_t namelen)
{	return _rilDevice.driver->ops->opsSocket.connect(device, socket, name, namelen);	}
int RilDevice_Disconnect(struct RilDevice *device, struct Socket *socket)
{	return _rilDevice.driver->ops->opsSocket.disconnect(device, socket);	}
int RilDevice_Send(struct RilDevice *device, struct Socket *socket, void *data, size_t size, int flags)
{	return _rilDevice.driver->ops->opsSocket.send(device, socket, data, size, flags);	}
int RilDevice_SendTo(struct RilDevice *device, struct Socket *socket, void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
{	return _rilDevice.driver->ops->opsSocket.sendto(device, socket, data, size, flags, to, tolen);	}
int RilDevice_Recv(struct RilDevice *device, struct Socket *socket, void *mem, size_t size, int flags)
{	return _rilDevice.driver->ops->opsSocket.recv(device, socket, mem, size, flags);	}
int RilDevice_RecvFrom(struct RilDevice *device, struct Socket *socket, void *mem, size_t size, int flags, struct sockaddr *from, socklen_t *fromlen)
{	return _rilDevice.driver->ops->opsSocket.recvfrom(device, socket, mem, size, flags, from, fromlen);	}

/*********************************************************************************************

  * ril devices infomation api

  ********************************************************************************************/
char* RilDevice_Imei(void)
{	return (char *)_rilDevice.driver->status->imei;	}
char* RilDevice_Imsi(void)
{	return (char *)_rilDevice.driver->status->imsi;	}
